home *** CD-ROM | disk | FTP | other *** search
/ Aminet 52 / Aminet 52 (2002)(GTI - Schatztruhe)[!][Dec 2002].iso / Aminet / util / moni / Scout-src.lha / source / SmartReadArgs.c < prev    next >
C/C++ Source or Header  |  2002-09-16  |  22KB  |  677 lines

  1. /*
  2.  * SmartReadArgs.c -- CLI/Workbench transparent ReadArgs()
  3.  *
  4.  * $VER: SmartReadArgs.c 1.6 (7.9.98)
  5.  *
  6.  * Copyright 1998 by Thomas Aglassinger <agi@sbox.tu-graz.ac.at>
  7.  *
  8.  * Based on ExtReadArgs Copyright 1994,1995 by Stefan Ruppert
  9.  */
  10.  
  11. /****** SmartReadArgs/--history-- *******************************************
  12.  * HISTORY
  13.  *   Version 1.6, 7-Sep-1998
  14.  *
  15.  *   - Changed name to SmartReadArgs to avoid confusion with other work based
  16.  *     on the same material
  17.  *   - Changed function parameters for SmartReadArgs() so that no more SAS/c
  18.  *     specific values of argc/argv are required (Of course it still works
  19.  *     with SAS/c, but you have to provide the WBStartup from "outside").
  20.  *   - Changed all #include <clib/...> to #include <proto/..>, except for
  21.  *     <clib/alib_stdio_protos.h> in "test.c". Where the hell is this one?
  22.  *   - Added feature to ignore tooltypes that are not in the template
  23.  *   - Added some missing includes in SmartReadArgs.c so the source codes
  24.  *     compile without warnings
  25.  *   - Changed #include <debug.h> to #include "debug.h" and provided a proper
  26.  *     debug.h
  27.  *   - The WINDOW tooltype is handled properly even if it is not entirely
  28.  *     written in upper case.
  29.  *   - Requires "utility.library" to be open as Stricmp() is used several
  30.  *     times
  31.  *   - Changed from Printf() to printf() using stdio of amiga.lib to make the
  32.  *     code compile easier on non-SAS environments
  33.  *   - Changed autodoc tool to Robodoc
  34.  *   - Fixed enforcer hit if no tooltypes were provided at all
  35.  *   - Remove some "char filename[34]" stuff and replaced the array dimension
  36.  *     by MAXIMUM_FILENAME_LENGTH for future compatibility
  37.  *   - Cleaned-up autodocs
  38.  * ANCIENT HISTORY
  39.  *   ExtReadArgs() by Stefan Ruppert
  40.  *
  41.  *   See aminet:dev/misc/extrdargs_v1.5.lha for the original version.
  42.  *
  43.  *   $HISTORY
  44.  *   08.01.95 : 001.005 :  changed to ExtReadArgs()
  45.  *   24.09.94 : 001.004 :  now checks after ReadArgs the SIGBREAKF_CTRL_C
  46.  *                         flag, thus if anyone canceled during ReadArgs()
  47.  *                         help ExtReadArgs() fails
  48.  *   08.09.94 : 001.003 :  between two switches (no equal sign) there was
  49.  *                         no space, this is fixed
  50.  *   08.09.94 : 001.002 :  wb files now enclosed in quotes
  51.  *   04.09.94 : 001.001 :  bumped to version 1
  52.  *   19.05.94 : 000.001 :  initial
  53.  ***************************************************************************/
  54.  
  55. /* ------------------------------ include's ------------------------------- */
  56.  
  57. #define __USE_SYSBASE
  58.  
  59. #include "SmartReadArgs.h"
  60.  
  61. #include <exec/memory.h>
  62. #include <workbench/startup.h>
  63. #include <workbench/workbench.h>
  64. #include <dos/exall.h>
  65. #include <utility/tagitem.h>
  66.  
  67. #include <string.h>
  68.  
  69. #include <proto/dos.h>
  70. #include <proto/icon.h>
  71. #include <proto/exec.h>
  72. #include <proto/utility.h>
  73.  
  74. /* ---------------------------- local defines ----------------------------- */
  75.  
  76. #define TEMPSIZE                     512
  77. #ifndef MAX
  78. #define MAX(a,b)  (((a) > (b)) ? (a) : (b))
  79. #endif
  80.  
  81. #ifndef EOS
  82. #define EOS    '\0'
  83. #endif
  84.  
  85. #define MODE_MULTI      1
  86.  
  87. #define MAXIMUM_FILENAME_LENGTH 108
  88.  
  89. /* --------------------------- library bases ------------------------------ */
  90. extern struct Library *IconBase;
  91. extern struct Library *UtilityBase;
  92.  
  93. #ifdef __GNUC__
  94. extern struct WBStartup *_WBenchMsg;
  95. #endif
  96.  
  97. /* -------------------------- static prototypes --------------------------- */
  98.  
  99. static struct DiskObject *smart_get_icon(struct SmartArgs *args, struct WBStartup *wbarg);
  100. static void fstrcpy(struct SmartArgs *args, STRPTR string);
  101. static void get_arg_name(struct SmartArgs *args, STRPTR buffer, ULONG size, ULONG * modes);
  102. static void get_wbarg_name(struct WBArg *wbarg, STRPTR buffer, ULONG size);
  103. static BOOL is_in_template(STRPTR name, STRPTR template);
  104. extern void kprintf(const char *,...);
  105.  
  106. /****** SmartReadArgs/--background-- ****************************************
  107.  * COPYRIGHT
  108.  *   SmartReadArgs is Copyright 1998 Thomas Aglassinger
  109.  *
  110.  *   ExtReadArgs, its prequel, is Copyright 1994,1995 Stefan Ruppert
  111.  *
  112.  *   Permission is granted to freely distribute the material (also only
  113.  *   parts of it) as long this ReadMe is included and all the copyright
  114.  *   notes are left unaltered except for a description of your changes.
  115.  * MOTIVATION
  116.  *   The way of parsing ToolTypes provided by "icon.library" is rather
  117.  *   clumsy. This is particular annoying as many programmers and users got
  118.  *   used to ReadArgs(), which does the argument handling for many CLI
  119.  *   commands and ARexx ports.
  120.  *
  121.  *   Unfortunately, ReadArgs lacks a interface to Workbench tooltypes, thus
  122.  *   its usage preventes your programs from being started from Workbench.
  123.  *
  124.  *   SmartReadArgs() copies all Workbench arguments in a single string and
  125.  *   passes this string to the ReadArgs() function. If started from CLI, it
  126.  *   calls ReadArgs() without this step.
  127.  * AUTHOR
  128.  *   Stefan Ruppert wrote most parts of the source code, designed the general
  129.  *   interface and implemented loads of nice features. Basically he did the
  130.  *   "hard work".
  131.  *
  132.  *   He got the main idea for the implementation from Stefan Winterstein,
  133.  *   the author of ARoach.
  134.  *
  135.  *   Thomas Aglassinger <agi@sbox.tu-graz.ac.at> did some minor changes,
  136.  *   established a more consistent naming schema, reworked the documentation
  137.  *   and also added support for gcc/libnix.
  138.  *
  139.  *   Contact him in case of problems or if you made some enhancements.
  140.  *
  141.  *   Updates are available from aminet:dev/misc/SmartReadArgs.lha.
  142.  * DISCLAIMER
  143.  *   There is no warranty for this software package. Although the author
  144.  *   has tried to prevent errors, he can't guarantee that the software
  145.  *   package described in this document is 100% reliable. You are
  146.  *   therefore using this material at your own risk. The author cannot be
  147.  *   made responsible for any damage which is caused by using this
  148.  *   software package.
  149.  ****************************************************************************/
  150.  
  151. /* The define below is used to rename the example main() used in the autodoc
  152.  * to dummy_main(). Using two main()s would cause problems for the linker. */
  153. #define main dummy_main
  154.  
  155. /****** SmartReadArgs/SmartReadArgs ******************************************
  156.  * NAME
  157.  *   SmartReadArgs -- Workbench/CLI transparent ReadArgs().
  158.  * SYNOPSIS
  159.  *   error = SmartReadArgs(wb_startup, smart_args);
  160.  * 
  161.  *   LONG SmartReadArgs(struct WBStartup *, struct SmartArgs *);
  162.  * FUNCTION
  163.  *   This function is a CLI/Workbench transparent interface to ReadArgs().
  164.  *
  165.  *   In case of a Workbench start, it analyzes the WBStartup message and
  166.  *   possible tooltypes. These are converted to a text string that can be
  167.  *   passed to ReadArgs() like before.
  168.  *
  169.  *   Tooltypes that are not part of the template are ignored. This includes
  170.  *   tooltypes being disabled with "(...)", NewIcons image data on systems
  171.  *   without NewIcons installed and all this «« Icon by some idiot »» crap.
  172.  * 
  173.  *   If the application was stared from CLI, it simply calls ReadArgs()
  174.  *   without the conversion step.
  175.  *
  176.  *   If all went well you get a return value of zero. This means the passed
  177.  *   arguments fit the template and are ready to use. Otherwise you get a
  178.  *   IoErr()-like return code.
  179.  * INPUTS
  180.  *    wb_startup - Workbench startup message. Refer to your compiler manual
  181.  *        to learn how to obtain it. If this is NULL, the program was
  182.  *        started from CLI.
  183.  *    smart_args - structure which holds all information used by
  184.  *        SmartReadArgs(). You have to setup the following fields before the
  185.  *        call:
  186.  *
  187.  *        sa_Template - The template passed to ReadArgs()
  188.  *        sa_Parameter - ReadArgs() LONG WORD array to hold the arguments
  189.  *        sa_FileParameter - number of Argument in the template to use
  190.  *            for the files passed via WBStartup->sm_ArgList or -1, that
  191.  *            means you don't want any files
  192.  *        sa_Window - Window description string to open when the program
  193.  *            is started from the workbench. NULL means no window. If the
  194.  *            icon has a WINDOW tooltype, this value is ignored.
  195.  *        sa_RDArgs - RDArgs structure to use for ReadArgs() call. This
  196.  *            can be used to provide extended help.
  197.  *        sa_Buffer - Pointer to a buffer to use for the Workbench startup
  198.  *            or NULL, that means SmartReadArgs() allocates a buffer for you
  199.  *        sa_BufferSize - Size of the optional buffer. If it is smaller than
  200.  *            SA_MINIMUM_BUFFER_SIZE it will be adjusted.
  201.  *
  202.  *        All other fields should be set to NULL.
  203.  * RESULTS
  204.  *   Zero for success. You can check the sa_Flags field for the
  205.  *   SAF_WORKBENCH flag to learn how the program was started.
  206.  *
  207.  *   Otherwise an IoErr()-like error code is returned. This can be passed
  208.  *   directly to PrintFault() or similar.
  209.  * NOTES
  210.  *   Always call SmartFreeArgs(), even if SmartReadArgs() failed! See example
  211.  *   below.
  212.  *
  213.  *   This function requires "dos.library", "icon.library" and
  214.  *   "utility.library" to be opened by the application. Normally this
  215.  *   already has been done by the compiler startup code.
  216.  *
  217.  *   There is a not widely known feature of ReadArgs(): with templates like
  218.  *   "FROM/M/A,TO/A", you can select the files from workbench performing the
  219.  *   following steps:
  220.  *
  221.  *   - Select the program
  222.  *   - Select the FROM files
  223.  *   - Select and double click the TO file
  224.  *
  225.  *   This is available because ReadArgs() grabs the last string from a
  226.  *   multi-argument FROM and uses it as the TO parameter, if none is passed
  227.  *   explicitely.
  228.  * BUGS
  229.  *   There are some known problems when used with GCC, mostly related to the
  230.  *   fact that I never bothered creating a useable developer environment
  231.  *   around it (and I'm not sure if this is even possible >:) ...):
  232.  *
  233.  *   - Debugging output shows up in the console instead of SER:. Does
  234.  *     debug.lib exist for gcc? (Wasn't there this strange hunk2gcc
  235.  *     converter?)
  236.  *   - "Read from 0" Enforcer hit in SmartReadArgs(). Couldn't figure out
  237.  *     the exact location yet because of the asynchronous debugging output
  238.  *     mentioned above.
  239.  *
  240.  *   For someone with a reasonable experience with GCC, it should be easy to
  241.  *   fix this.
  242.  *
  243.  *   The SAS/c implementation does not have these problems.
  244.  * SEE ALSO
  245.  *   SmartFreeArgs(), dos.library/ReadArgs(), icon.library/GetDiskObjectNew()
  246.  * EXAMPLE
  247.  *   The main archiev comes with a "test.c" and a couple of icons to start
  248.  *   the corresponding executable "test". Take a look at the source code and
  249.  *   play with it.
  250.  *
  251.  *   See below for a smaller code segment that expects the "dos.library",
  252.  *   "icon.library" and "utility.library" to be open already.
  253.  * SOURCE
  254.  */
  255. /****************************************************************************/
  256. LONG SmartReadArgs(struct WBStartup * wb_startup, struct SmartArgs * args)
  257. {
  258.    LONG error;
  259.  
  260.    args->sa_Flags = 0;
  261.  
  262.    if (wb_startup != NULL)
  263.    {
  264.       struct WBArg *wbarg = wb_startup->sm_ArgList;
  265.       LONG arg_counter = 0;
  266.  
  267.       while (arg_counter < wb_startup->sm_NumArgs)
  268.       {
  269.          wbarg += 1;
  270.          arg_counter += 1;
  271.       }               
  272.    }
  273.  
  274.    if (wb_startup != NULL)
  275.    {
  276.       if (!(args->sa_RDArgs = AllocDosObject(DOS_RDARGS, NULL)))
  277.       {
  278.          return (ERROR_NO_FREE_STORE);
  279.       }
  280.       else
  281.       {
  282.          args->sa_Flags |= SAF_ALLOCRDARGS;
  283.  
  284.          if (!args->sa_Buffer)
  285.          {
  286.             args->sa_BufferSize = MAX(SA_MINIMUM_BUFFER_SIZE, args->sa_BufferSize);
  287.             args->sa_Buffer = AllocMem(args->sa_BufferSize, MEMF_ANY);
  288.             args->sa_Flags |= SAF_ALLOCBUFFER;
  289.          }
  290.  
  291.          if (!args->sa_Buffer)
  292.             return (ERROR_NO_FREE_STORE);
  293.          else
  294.          {
  295.             struct DiskObject *dobj;
  296.  
  297.             args->sa_ActualPtr = args->sa_Buffer;
  298.             args->sa_EndPtr = args->sa_Buffer + args->sa_BufferSize - 1;
  299.  
  300.             if (!(dobj = smart_get_icon(args, wb_startup)))
  301.             {
  302.                return (ERROR_OBJECT_NOT_FOUND);
  303.             }
  304.             else
  305.             {
  306.                struct WBArg *wbarg = args->sa_WBArg;
  307.                ULONG num = args->sa_NumArgs;
  308.  
  309.                STRPTR *tooltypes = (STRPTR *) dobj->do_ToolTypes;
  310.                STRPTR name;
  311.                STRPTR temp;
  312.                STRPTR ptr;
  313.  
  314.                if (num > 1 && args->sa_FileParameter >= 0 && (temp = AllocMem(TEMPSIZE, MEMF_ANY)))
  315.                {
  316.                   ULONG modes = 0;
  317.  
  318.                   get_arg_name(args, temp, TEMPSIZE, &modes);
  319.                   fstrcpy(args, temp);
  320.                   fstrcpy(args, " ");
  321.  
  322.                   /* no "/M" specifier in the ReadArgs() template, thus use only the first file */
  323.                   if (modes != MODE_MULTI)
  324.                      num = 2;
  325.  
  326.                   while (num > 1)
  327.                   {
  328.                      get_wbarg_name(wbarg, temp, TEMPSIZE);
  329.                      fstrcpy(args, "\"");
  330.                      fstrcpy(args, temp);
  331.                      fstrcpy(args, "\" ");
  332.                      num--;
  333.                      wbarg++;
  334.                   }
  335.  
  336.                   FreeMem(temp, TEMPSIZE);
  337.                }
  338.  
  339.                if (tooltypes)
  340.                {
  341.                   while (*tooltypes)
  342.                   {
  343.                      ptr = *tooltypes;
  344.                      name = ptr;
  345.  
  346.                      /* check if this tooltype enabled and part of the
  347.                       * template */
  348.                      if ((*ptr != '(')
  349.                          && is_in_template(name, args->sa_Template))
  350.                      {
  351.                         while (*ptr != '=' && *ptr != EOS)
  352.                            ptr++;
  353.  
  354.                         if (*ptr == '=')
  355.                         {
  356.                            *ptr = EOS;
  357.  
  358.                            if (!Stricmp(name, "WINDOW"))
  359.                            {
  360.                               STRPTR win;
  361.                               if ((win = AllocVec(strlen(ptr + 1) + 1, MEMF_ANY)))
  362.                               {
  363.                                  strcpy(win, ptr + 1);
  364.                                  args->sa_Window = win;
  365.                                  args->sa_Flags |= SAF_ALLOCWINDOW;
  366.                               }
  367.  
  368.                            }
  369.                            else
  370.                            {
  371.                               fstrcpy(args, name);
  372.  
  373.                               /* enclose the argument in "" */
  374.                               if (*(ptr + 1) == '"')
  375.                               {
  376.                                  fstrcpy(args, "=");
  377.                                  fstrcpy(args, ptr + 1);
  378.                               }
  379.                               else
  380.                               {
  381.                                  fstrcpy(args, "=\"");
  382.                                  fstrcpy(args, ptr + 1);
  383.                                  fstrcpy(args, "\"");
  384.                               }
  385.  
  386.                               *ptr = '=';
  387.                            }
  388.                         }
  389.                         else
  390.                            fstrcpy(args, name);
  391.  
  392.                         fstrcpy(args, " ");
  393.                      }
  394.                      tooltypes++;
  395.                   }             /* while (*tooltypes) */
  396.                }                /* if (tooltypes) */
  397.                fstrcpy(args, "\n");
  398.             }
  399.          }
  400.       }
  401.  
  402.       args->sa_RDArgs->RDA_Source.CS_Buffer = args->sa_Buffer;
  403.       args->sa_RDArgs->RDA_Source.CS_Length = strlen(args->sa_Buffer);
  404.  
  405.       args->sa_Flags |= SAF_WORKBENCH;
  406.    }
  407.  
  408.    // ReadArgs() scheint bei fehlerfreier Arbeit IoErr() nicht neu zu setzen, darum machen wir das hier selbst
  409.    SetIoErr(0);
  410.    args->sa_FreeArgs = ReadArgs(args->sa_Template, args->sa_Parameter, args->sa_RDArgs);
  411.  
  412.    if (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
  413.    {
  414.       SetIoErr(ERROR_BREAK);
  415.    }
  416.  
  417.    if ((error = IoErr()) == 0 && (wb_startup != NULL))
  418.    {
  419.       if (args->sa_Window)
  420.       {
  421.          args->sa_WindowFH = Open(args->sa_Window, MODE_NEWFILE);
  422.          if (args->sa_WindowFH)
  423.          {
  424.             args->sa_OldOutput = SelectOutput(args->sa_WindowFH);
  425.             args->sa_OldInput = SelectInput(args->sa_WindowFH);
  426.          }
  427.       }
  428.    }
  429.  
  430.    return (error);
  431. }
  432.  
  433. /****** SmartReadArgs/SmartFreeArgs ******************************************
  434.  * NAME
  435.  *   SmartFreeArgs -- Free all resources allocated by SmartReadArgs().
  436.  * SYNOPSIS
  437.  *   SmartFreeArgs(smart_args);
  438.  *
  439.  *   void SmartFreeArgs(struct SmartArgs *);
  440.  * FUNCTION
  441.  *   Free all resources allocated by a previous call to SmartReadArgs().
  442.  * INPUTS
  443.  *   smart_args - Same pointer as passed to SmartReadArgs() before
  444.  * NOTES
  445.  *   Always call SmartFreeArgs(), even if SmartReadArgs() failed! Take a look
  446.  *   at the example for SmartReadArgs().
  447.  * SEE ALSO
  448.  *   SmartReadArgs()
  449.  ****************************************************************************/
  450. void SmartFreeArgs(struct SmartArgs *args)
  451. {
  452.    /* FreeArgs() can handle a NULL pointer */
  453.    FreeArgs(args->sa_FreeArgs);
  454.  
  455.    if (args->sa_Flags & SAF_ALLOCRDARGS)
  456.       if (args->sa_RDArgs)
  457.          FreeDosObject(DOS_RDARGS, args->sa_RDArgs);
  458.  
  459.    if (args->sa_Flags & SAF_ALLOCBUFFER)
  460.       FreeMem(args->sa_Buffer, args->sa_BufferSize);
  461.  
  462.    if (args->sa_WindowFH)
  463.    {
  464.       SelectOutput(args->sa_OldOutput);
  465.       SelectInput(args->sa_OldInput);
  466.       Close(args->sa_WindowFH);
  467.    }
  468.  
  469.    if (args->sa_Flags & SAF_ALLOCWINDOW && args->sa_Window)
  470.       FreeVec(args->sa_Window);
  471. }
  472.  
  473. /* This code was grapped from IconImage/wbarg.c/IconFromWBArg()
  474.  * Commodore-Amiga Example code
  475.  */
  476. static struct DiskObject *smart_get_icon(struct SmartArgs *args, struct WBStartup *wb_startup)
  477. {
  478.    struct DiskObject *dob = NULL;
  479.    struct WBArg *wbarg = wb_startup->sm_ArgList;
  480.    ULONG num = wb_startup->sm_NumArgs;
  481.  
  482.    UBYTE work_name[MAXIMUM_FILENAME_LENGTH];
  483.    BPTR old_lock, new_lock;
  484.  
  485.    /* Copy the WBArg contents */
  486.    strncpy(work_name, wbarg->wa_Name, MAXIMUM_FILENAME_LENGTH);
  487.  
  488.    new_lock = DupLock(wbarg->wa_Lock);
  489.    if (new_lock)
  490.    {
  491.       /* go to the directory where the icon resides */
  492.       old_lock = CurrentDir(new_lock);
  493.  
  494.       dob = GetDiskObjectNew(work_name);
  495.  
  496.       /* test, if the first icon is a project icon and if so, get its icon */
  497.       if (wb_startup->sm_NumArgs > 1)
  498.       {
  499.          BPTR new_lock2;
  500.  
  501.          if ((new_lock2 = DupLock(wbarg[1].wa_Lock)))
  502.          {
  503.             struct DiskObject *prj;
  504.  
  505.             CurrentDir(new_lock2);
  506.  
  507.             UnLock(new_lock);
  508.             new_lock = new_lock2;
  509.  
  510.             strncpy(work_name, wbarg[1].wa_Name, MAXIMUM_FILENAME_LENGTH);
  511.  
  512.             if ((prj = GetDiskObjectNew(work_name)))
  513.             {
  514.                if (prj->do_Type == WBPROJECT)
  515.                {
  516.                   BPTR test;
  517.  
  518.                   /* if this is only an icon skip it */
  519.                   if (!(test = Lock(work_name, SHARED_LOCK)))
  520.                   {
  521.                      wbarg++;
  522.                      num--;
  523.                   }
  524.                   else
  525.                      UnLock(test);
  526.  
  527.                   if (dob)
  528.                      FreeDiskObject(dob);
  529.  
  530.                   dob = prj;
  531.                }
  532.             }
  533.          }
  534.       }
  535.  
  536.       /* go back to where we used to be */
  537.       CurrentDir(old_lock);
  538.  
  539.       /* release the duplicated lock */
  540.       UnLock(new_lock);
  541.  
  542.       args->sa_WBArg = wbarg + 1;
  543.       args->sa_NumArgs = num;
  544.    }
  545.  
  546.    return (dob);
  547. }
  548.  
  549. static void fstrcpy(struct SmartArgs *args, STRPTR string)
  550. {
  551.    STRPTR ptr = args->sa_ActualPtr;
  552.    STRPTR end = args->sa_EndPtr;
  553.  
  554.    while (ptr < end && *string)
  555.       *ptr++ = *string++;
  556.  
  557.    *ptr = EOS;                  /* Mark end of string */
  558.  
  559.    args->sa_ActualPtr = ptr;
  560. }
  561.  
  562. static void get_arg_name(struct SmartArgs *args, STRPTR buffer, ULONG size, ULONG * modes)
  563. {
  564.    ULONG num = args->sa_FileParameter;
  565.    STRPTR ptr = args->sa_Template;
  566.  
  567.    *modes = 0;
  568.  
  569.    while (num > 0)
  570.    {
  571.       while (*ptr != ',' && *ptr != EOS)
  572.          ptr++;
  573.  
  574.       if (*ptr == ',')
  575.          ptr++;
  576.       num--;
  577.    }
  578.  
  579.    if (*ptr != EOS)
  580.    {
  581.       while (*ptr != ',' && *ptr != '/' && *ptr != EOS && size > 0)
  582.       {
  583.          *buffer++ = *ptr++;
  584.          size--;
  585.       }
  586.  
  587.       while (*ptr == '/')
  588.       {
  589.          ptr++;
  590.  
  591.          if (*ptr == 'M' || *ptr == 'm')
  592.             *modes = MODE_MULTI;
  593.  
  594.          ptr++;
  595.       }
  596.    }
  597.  
  598.    *buffer = EOS;
  599. }
  600.  
  601. static void get_wbarg_name(struct WBArg *wbarg, STRPTR buffer, ULONG size)
  602. {
  603.    BPTR new;
  604.  
  605.    if ((new = DupLock(wbarg->wa_Lock)))
  606.    {
  607.       if (!NameFromLock(new, buffer, size))
  608.          *buffer = EOS;
  609.       else if (!AddPart(buffer, wbarg->wa_Name, size))
  610.          *buffer = EOS;
  611.  
  612.       UnLock(new);
  613.    }
  614.    else
  615.       *buffer = EOS;
  616. }
  617.  
  618. /* Enable extended debugging for is_in_template() */
  619. #if 0
  620. #define D2(x) x
  621. #else
  622. #define D2(x) /* nufin */
  623. #endif
  624. static BOOL is_in_template(STRPTR name, STRPTR template)
  625. {
  626.    BOOL found = FALSE;
  627.    STRPTR current_word = template;
  628.    BOOL skip_switch = FALSE;
  629.    size_t name_length;
  630.  
  631.    /* Evaluate length of name part of whole tooltype */
  632.    name_length = 0;
  633.    while ((name[name_length] != EOS)
  634.           && (name[name_length] != '='))
  635.    {
  636.       name_length += 1;
  637.    }
  638.  
  639.    while ((current_word[0] != '\0') && (!found))
  640.    {
  641.       STRPTR next_word = strpbrk(current_word, "/=,");
  642.       size_t current_word_length;
  643.  
  644.       if (next_word == NULL)
  645.       {
  646.          next_word = current_word + strlen(current_word);
  647.       }
  648.       current_word_length = next_word - current_word;
  649.  
  650.       if (skip_switch)
  651.       {
  652.          skip_switch = FALSE;
  653.       }
  654.       else
  655.       {
  656.          if ((name_length == current_word_length)
  657.              && !Strnicmp(name, current_word, name_length))
  658.          {
  659.             found = TRUE;
  660.          }
  661.       }
  662.  
  663.       current_word = next_word;
  664.       if (current_word[0] != '\0')
  665.       {
  666.          if (current_word[0] == '/')
  667.          {
  668.             skip_switch = TRUE;
  669.          }
  670.          current_word += 1;
  671.       }
  672.    }
  673.  
  674.    return found;
  675. }
  676.  
  677.